package org.boticelli.model;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

import org.boticelli.util.DateUtil;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Index;

@NamedQueries(value = {
        @NamedQuery(name = "LogEntry.findByDay", query = "select l from LogEntry l "
            + "where l.day = :day order by l.moment"),
        @NamedQuery(name = "LogEntry.findByAll", query = "select l from LogEntry l "),
        @NamedQuery(name = "LogEntry.getMinAndMaxDay", query = "select min(l.day),max(l.day) from LogEntry l "),
        @NamedQuery(name = "LogEntry.findBySearch", query = "select l from LogEntry l "
                + "where text like :search or ident like :search order by l.moment") })
@Entity
@Table(name = "log")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class LogEntry
        implements Serializable
{
    private static final int MAX_MESSAGE_LENGTH = 1200; 
    
    private static final long serialVersionUID = -4988153521093638089L;

    private Long id;

    private Timestamp moment;

    private LogType type;

    private String ident;

    private String text;

    private Integer day;
    
    public LogEntry()
    {
        
    }
    
    public LogEntry(Timestamp moment, String ident, String text, LogType type)
    {
        setMoment(moment);
        setIdent(ident);
        setText(text);
        setType(type);
    }
    
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId()
    {
        return id;
    }

    @Column(nullable = false)
    public Timestamp getMoment()
    {
        return moment;
    }

    @Column
    public String getIdent()
    {
        return ident;
    }

    @Column(nullable = false, length = MAX_MESSAGE_LENGTH)
    public String getText()
    {
        return text;
    }

    @Column(nullable = false)
    public LogType getType()
    {
        return type;
    }

    public void setId(Long id)
    {
        this.id = id;
    }

    public void setMoment(Timestamp moment)
    {
        this.moment = moment;
        
        Calendar cal=Calendar.getInstance();
        cal.setTime(moment);
        long offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET);
        
        setDay((int)((moment.getTime()+offset)/DateUtil.MILLISECONDS_PER_DAY));
    }

    public void setIdent(String ident)
    {
        this.ident = ident;
    }

    public void setText(String text)
    {
        this.text = text;
    }

    public void setType(LogType type)
    {
        this.type = type;
    }
    
    @Column()
    @Index(name = "idx_day")
    public Integer getDay()
    {
        return day;
    }

    public void setDay(Integer day)
    {
        this.day = day;
    }

    /**
     * Creates a list of LogElements from the given input. the given text is
     * split into substrings that are maximally {@link #MAX_MESSAGE_LENGTH} characters long.
     * 
     * @param ident
     * @param text
     * @param type
     * @return list of logs
     */
    public static List<LogEntry> create(String ident, String text, LogType type)
    {
        Timestamp now = new Timestamp(System.currentTimeMillis());

        List<LogEntry> logs = new ArrayList<LogEntry>();
        while (text.length() > MAX_MESSAGE_LENGTH)
        {
            String first = text.substring(0, MAX_MESSAGE_LENGTH);
            text = text.substring(MAX_MESSAGE_LENGTH);

            logs.add( new LogEntry(now,ident,first,type));
        }
        logs.add( new LogEntry(now,ident,text,type));
        return logs;
    }
}
